﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using RFServer.Database;

namespace RFServer.ServiceWCF
{
    [ServiceContract]
    interface ILocalService : IMainService
    {
        [OperationContract]
        void FileRename(string oldPath, string newPath);

        [OperationContract]
        void FileDelete(string path);

        [OperationContract]
        void ClearDatabase();

        [OperationContract]
        void ClearEmptyTags();

        [OperationContract]
        bool TagExists(string tag);

        [OperationContract]
        string GetServerApplication();
    }

    class LocalService : ILocalService
    {
        public string[] Select(string[] keywords)
        {
            ServiceCommonActions.LogAdvanced("localhost", "SELECT", keywords);

            return ServiceCommonActions.Select(keywords);
        }

        public string[] Tags(string[] keywords)
        {
            ServiceCommonActions.LogAdvanced("localhost", "TAGS", keywords);

            return ServiceCommonActions.Tags(keywords);
        }

        public bool Insert(string[] keywords)
        {
            ServiceCommonActions.LogAdvanced("localhost", "INSERT", keywords);

            return ServiceCommonActions.Insert(keywords);
        }

        public bool Delete(string[] keywords)
        {
            ServiceCommonActions.LogAdvanced("localhost", "DELETE", keywords);

            return ServiceCommonActions.Delete(keywords);
        }

        /// <summary>
        /// Пользователь переместил файл. Отмечаем это в базе данных
        /// </summary>
        /// <param name="oldPath">Файл, который перещали</param>
        /// <param name="newPath">Файл, в который переместили</param>

        public void FileRename(string oldPath, string newPath)
        {
            Storage.Rename(("rename|object|" + oldPath + '|' + newPath).Split('|'));
        }

        /// <summary>
        /// Пользователь удалили файл. Отмечаем это в базе данных
        /// </summary>
        /// <param name="path">Файл, который удалили</param>

        public void FileDelete(string path)
        {
            Storage.Delete(("delete|object|" + path).Split('|'));
        }

        /// <summary>
        /// Очистка всей информации в базе данных
        /// </summary>

        public void ClearDatabase()
        {
            ServiceCommonActions.LogAdvanced("localhost", "Clear database", null);

            Storage.ClearDatabase();
        }

        /// <summary>
        /// Удаление пустых категорий
        /// </summary>

        public void ClearEmptyTags()
        {
            ServiceCommonActions.LogAdvanced("localhost", "Remove empty tags", null);

            Storage.RemoveUnusedTags();
        }

        /// <summary>
        /// Остановка сервера (если сервер запущен как  служба Windows,
        /// то остановка невозможна). Удаленная установка сервера ОТКЛЮЧЕНА,
        /// т.к. функция останавливает службы WCF, когда взаимодействие с
        /// клиентом не окончено, и последний получает исключение
        /// </summary>

        private bool Shutdown()
        {
            if (Setup.IsService)
                return false;

            Setup.Log("[server]: Warngin: SHUTDOWN command is unsupported");
            Setup.Log("[server]: SHUTDOWN command has arrived");

            /* Уничтожение консоли                              */

            Setup.ConsoleForm = null;

            /* Остановка служб                                  */
            
            ServiceControl.Stop();

            return true;
        }

        /// <summary>
        /// Проверка тэга на существование
        /// </summary>

        public bool TagExists(string tag)
        {
            return Storage.TagExists(tag);
        }
        
        /// <summary>
        /// Путь к исполняемому файлу сервера
        /// </summary>
        /// <returns>полный путь к exe-файлу</returns>

        public string GetServerApplication()
        {
            ServiceCommonActions.LogAdvanced("localhost", "Getting server exe-name", null);

            return System.Reflection.Assembly.GetExecutingAssembly().Location;
        }

        /// <summary>
        /// Функция устанавливает соединение со службой
        /// LocalService через именованные каналы
        /// </summary>
        /// <returns>Соеденине с LocalService, null если удаленный хост не отвечает</returns>

        public static ILocalService Connect()
        {
            EndpointAddress address = new EndpointAddress(Setup.ServiceLocalAddress);
            NetNamedPipeBinding binding = new NetNamedPipeBinding();

            binding.Security.Mode = NetNamedPipeSecurityMode.None;

            try
            {
                ChannelFactory<ILocalService> factory = new ChannelFactory<ILocalService>(binding, address);
                return factory.CreateChannel();
            }
            catch (EndpointNotFoundException)
            {
                return null;
            }
        }

        /// <summary>
        /// Функция закрывает соединение со службой
        /// LocalService через именованные каналы
        /// </summary>
        /// <param name="service">Соеденине с LocalService</param>

        public static void Disconnect(ILocalService service)
        {
            ICommunicationObject channel = service as ICommunicationObject;

            if (service == null)
                return;

            channel.Close();
        }
    }
}
